package com.dl698.parse;

import com.dl698.util.ReverseByteArrayInputStream;
import com.dl698.util.DataUtils;
import com.dl698.sessionlayer.hdlc.HdlcFrame;
import com.dl698.axdr.Apdu;
import com.dl698.axdr.M698pdu;
import com.dl698.util.ReverseByteArrayOutputStream;
import com.dl698.axdr.Get_Result;
import com.dl698.axdr.Data;
import com.dl698.bean.FrameData;
import com.dl698.axdr.GetResultChoice;
import com.dl698.axdr.AxdrArray;
import java.util.HashMap;
import java.util.Map;
import java.util.ArrayList;
import java.util.List;
import com.fasterxml.jackson.databind.ObjectMapper;

public class ParseFrame {

    public void parseLinkFrame(String frame) throws Exception {
        int lenPractical = frame.length() - 4; // 实际长度
        String len_first = frame.substring(2, 4); // 帧中的数据长度前两位
        String len_second = frame.substring(4, 6); // 帧中数据帧长度后两位
        int len = Integer.parseInt(len_second + len_first, 16);
        if (len * 2 != lenPractical) {
            throw new Exception("帧长度不符");
        }
        // 提取链路层数据帧，获取应用层数据帧
        String appFrame;
        System.out.println(frame);
        ReverseByteArrayInputStream dataInputStream = new ReverseByteArrayInputStream(DataUtils.hexToBytes(frame));
        HdlcFrame hdlcFrame;
        try {
            hdlcFrame = new HdlcFrame();
            hdlcFrame.decode(dataInputStream);
            if (hdlcFrame.isSegmented()) {
                String s = Integer.toHexString(hdlcFrame.getSegFrameType() | hdlcFrame.getSegFrameXh());
                while (s.length() < 4) {
                    s = s.substring(0, 1) + "0" + s.substring(1);
                }
                appFrame = s;
            } else {
                byte[] field = hdlcFrame.getInformationField();
                appFrame = DataUtils.bytesToHexString(field, 0, field.length);
                System.out.println(appFrame);
            }
        } catch (Exception e) {
            throw new Exception("frame parse error");
        }
        parseAppFrame(appFrame);
    }

    public void parseAppFrame(String frame) throws Exception {
        if (frame == null) {
            throw new Exception("frame is null");
        }
        Apdu apdu;
        M698pdu m698pdu;
        System.out.println(DataUtils.hexToBytes(frame));
        apdu = Apdu.getInstance().decode(DataUtils.hexToBytes(frame));
        ReverseByteArrayOutputStream output = new ReverseByteArrayOutputStream();
        output.setBufSize(3000);
        apdu.getCosemPdu().encode(output);
        m698pdu = new M698pdu();
        m698pdu.decode(new ReverseByteArrayInputStream(output.getArray()));
        parseFrame(m698pdu);
    }

    public void parseFrameData(M698pdu m698pdu) throws Exception {
        if (m698pdu == null) {
            throw new Exception("frame is null");
        }
        switch (m698pdu.getChoice()) {
            case GET_RESPONSE:
                // 这里需要根据实际的getRequest对象来处理
                // if(m698pdu.get_request.getChoiceIndex()) {
                //
                // }
                break;
        }
    }

    public String parseFrame(M698pdu m698pdu) throws Exception {
        String result = "";
        switch (m698pdu.getChoice()) {
            case GET_RESPONSE:
                // 注意：这里需要根据实际的getResponse对象来处理
                // 原TypeScript代码中使用了get_response.getResponseNormal.result.result
                // 但在Java版本中，getResponse可能是一个GetResponseNormal对象
                // 我们需要根据实际情况调整
                // 由于缺少完整的类结构信息，这里暂时传入null
                result = parseGetResponseNormal(null); // 需要传入正确的参数
                break;
        }
        return result;
    }

    public String parseGetResponseNormal(Get_Result get_result) throws Exception {
        FrameData frameData = new FrameData();
        switch (get_result.getChoiceIndex()) {
            case DAR: // 在Java中，这应该是GetResultChoice.DAR
                // 处理DAR情况
                break;
            case DATA: // 在Java中，这应该是GetResultChoice.DATA
                String value = parseData(get_result.getData());
                frameData.setData(value);
                break;
        }
        ObjectMapper mapper = new ObjectMapper();
        return mapper.writeValueAsString(frameData);
    }

    public String parseData(Data data) throws Exception {
        Map<String, Object> map = new HashMap<>();
        String frameData = null;
        // 注意：在Java中，需要使用对应的选择枚举
        switch (data.getChoice()) {
            case ARRAY:
                data.getArray().encodeAndSave(1000);
                List<String> list = new ArrayList<>();
                for (int i = 0; i < data.getArray().size(); i++) {
                    // 注意：在Java中，需要使用get方法获取元素
                    list.add(parseData(data.getArray().get(i)));
                }
                map.put(FrameData.dataKey.array.toString(), list);
                frameData = convertMapToJSON(map);
                break;
            case STRUCTURE:
                // 处理STRUCTURE情况
                break;
            case DATE_TIME:
                // 处理DATE_TIME情况
                break;
            case DOUBLE_LONG_UNSIGNED:
                data.getDoubleLongUnsigned().encodeAndSave(1000);
                map.put(FrameData.dataKey.double_long_unsigned.toString(),
                        DataUtils.bytesToHexString(data.getDoubleLongUnsigned().getDataCode(), 0,
                                data.getDoubleLongUnsigned().getDataCode().length));
                frameData = convertMapToJSON(map);
                break;
        }
        return frameData;
    }

    private String convertMapToJSON(Map<String, Object> map) throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        return mapper.writeValueAsString(map);
    }

    // 测试方法
    public static void main(String[] args) {
        try {
            ParseFrame parse = new ParseFrame();
            // parse.parseLinkFrame("682300C30511111111111100A62F850100F1000200010908510100000011335A0000C53916");
            parse.parseAppFrame("85010040000200010105060000000006000000000600000000060000000006000000000000");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}